package com.jpsl.core.reflection.property;

import com.jpsl.core.reflection.property.f.ByFieldMetaClass;
import com.jpsl.core.reflection.property.m.ByMethodMetaClass;
import com.jpsl.core.util.Assert;

import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 懒王猫
 */
public abstract class MetaClasses {

    private static final Map<String, WeakReference<MetaClass>> META_CLASS_CACHE = new ConcurrentHashMap<>();

    public static final int BY_FIELD = 0;

    public static final int BY_METHOD = 1;

    /**
     * 默认通过反射字段获取 class 描述对象
     */
    public static MetaClass getMetaClass(Class<?> clazz) {
        return getMetaClass(clazz, BY_FIELD);
    }

    /**
     * 获取 class 描述对象
     *
     * @param clazz 类型
     * @param mode 模式: {@link MetaClasses#BY_FIELD} 通过反射字段; {@link MetaClasses#BY_METHOD} 通过反射方法
     */
    public static MetaClass getMetaClass(Class<?> clazz, int mode) {
        Assert.isTrue(mode == BY_FIELD || mode == BY_METHOD, "mode must be 'BY_FIELD' or 'BY_METHOD'");
        String name = clazz.getName() + "#" + mode;
        return Optional.ofNullable(META_CLASS_CACHE.get(name))
                .map(WeakReference::get)
                .orElseGet(() -> {
                    MetaClass metaClass = mode == BY_FIELD ? new ByFieldMetaClass(clazz) : new ByMethodMetaClass(clazz);
                    META_CLASS_CACHE.put(name, new WeakReference<>(metaClass));
                    return metaClass;
                });
    }

}
